"""
通用评论服务
"""
from typing import Dict, Any, Optional, List
from bson import ObjectId
from datetime import datetime
from motor.motor_asyncio import AsyncIOMotorDatabase
from fastapi import HTTPException, status

from app.utils.state_utils import get_default_state_code


class CommentService:
    def __init__(self, db: AsyncIOMotorDatabase):
        self.db = db
    
    async def add_comment(
        self,
        user: dict,
        entity_type: str,  # 'task', 'requirement', 'defect'
        entity_id: str,
        comment_in: dict
    ) -> dict:
        """添加评论"""
        try:
            # 验证实体ID格式
            if not ObjectId.is_valid(entity_id):
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="无效的实体ID格式"
                )
            
            # 构建集合名称
            collection_name = f"{entity_type}s"  # 转换为复数形式的集合名
            
            # 验证实体是否存在
            entity = await self.db[collection_name].find_one({"_id": ObjectId(entity_id)})
            if not entity:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail=f"{entity_type.capitalize()}不存在"
                )
            
            # 如果是回复评论，验证父评论是否存在
            parent_comment_id = comment_in.get("parent_comment_id")
            if parent_comment_id:
                # 构建父评论查询条件（兼容不同模块的字段命名）
                parent_comment_exists = await self.db[collection_name].find_one({
                    "_id": ObjectId(entity_id),
                    "comments.id": parent_comment_id,
                    "comments.status": "published"
                })
                if not parent_comment_exists:
                    # 尝试另一种方式查找父评论（兼容is_deleted字段）
                    parent_comment_exists = await self.db[collection_name].find_one({
                        "_id": ObjectId(entity_id),
                        "comments.id": parent_comment_id,
                        "comments.is_deleted": False
                    })
                    if not parent_comment_exists:
                        raise HTTPException(
                            status_code=status.HTTP_404_NOT_FOUND,
                            detail="父评论不存在或已被删除"
                        )
            
            # 获取默认状态
            default_status = await get_default_state_code(self.db, "comment") or "published"
            
            # 构建评论数据（使用通用字段名，但确保兼容性）
            comment = {
                "id": str(ObjectId()),
                "author_id": user["user_id"],
                "author_name": user["username"],
                "user_id": user["user_id"],  # 保持向后兼容
                "user_name": user["username"],  # 保持向后兼容
                "content": comment_in["content"],
                "parent_comment_id": parent_comment_id,
                "parent_id": parent_comment_id,  # 保持向后兼容
                "status": comment_in.get("status", default_status),
                "is_deleted": False,
                "created_at": datetime.utcnow(),
                "updated_at": None,
                "deleted_at": None
            }
            
            # 添加评论
            await self.db[collection_name].update_one(
                {"_id": ObjectId(entity_id)},
                {
                    "$push": {"comments": comment},
                    "$set": {"updated_at": datetime.utcnow()}
                }
            )
            
            # 更新评论计数
            current_comments = entity.get("comments", [])
            comment_count = len([
                c for c in current_comments 
                if c.get("status") != "deleted" and not c.get("is_deleted", False)
            ])
            await self.db[collection_name].update_one(
                {"_id": ObjectId(entity_id)},
                {"$set": {"comment_count": comment_count + 1}}
            )
            
            return {"message": "评论添加成功", "comment": comment}
            
        except HTTPException:
            raise
        except Exception as e:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail=f"添加评论失败: {str(e)}"
            )
    
    async def update_comment(
        self,
        user: dict,
        entity_type: str,
        entity_id: str,
        comment_id: str,
        comment_update: dict
    ) -> dict:
        """更新评论"""
        try:
            # 验证实体ID格式
            if not ObjectId.is_valid(entity_id):
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="无效的实体ID格式"
                )
            
            # 构建集合名称
            collection_name = f"{entity_type}s"
            
            # 查询实体和评论
            entity = await self.db[collection_name].find_one({"_id": ObjectId(entity_id)})
            if not entity:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail=f"{entity_type.capitalize()}不存在"
                )
            
            # 查找评论
            comments = entity.get("comments", [])
            comment_index = -1
            for i, comment in enumerate(comments):
                if comment.get("id") == comment_id:
                    comment_index = i
                    break
            
            if comment_index == -1:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="评论不存在"
                )
            
            comment = comments[comment_index]
            
            # 检查评论是否已被删除
            comment_status = comment.get("status", "published")
            is_deleted = comment.get("is_deleted", False)
            if comment_status == "deleted" or is_deleted:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="无法编辑已删除的评论"
                )
            
            # 权限检查：只有评论作者或管理员可以编辑
            # 兼容不同的作者ID字段名
            comment_author_id = str(comment.get("author_id", comment.get("user_id", "")))
            user_roles = user.get("roles", [])
            
            has_permission = (comment_author_id == user["user_id"] or "admin" in user_roles)
            
            if not has_permission:
                raise HTTPException(
                    status_code=status.HTTP_403_FORBIDDEN,
                    detail="无权限编辑此评论"
                )
            
            # 检查评论是否已被删除（如果要编辑内容，不允许）
            is_deleted = comment.get("is_deleted", False) or comment.get("status") == "deleted"
            is_restoring = comment_update.get("is_deleted") is False or comment_update.get("status") == "published"
            
            # 如果评论已删除，且用户不是要恢复它，则不允许编辑内容
            if is_deleted and not is_restoring and comment_update.get("content") is not None:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="无法编辑已撤回的评论"
                )
            
            # 更新评论
            update_fields = {"updated_at": datetime.utcnow()}
            
            if "content" in comment_update and comment_update["content"] is not None:
                # 如果评论已删除，不允许修改内容（除非是恢复）
                if is_deleted and not is_restoring:
                    raise HTTPException(
                        status_code=status.HTTP_400_BAD_REQUEST,
                        detail="无法编辑已撤回的评论"
                    )
                update_fields["content"] = comment_update["content"]
            
            if "status" in comment_update and comment_update["status"] is not None:
                update_fields["status"] = comment_update["status"]
                # 如果状态为deleted，设置删除时间
                if comment_update["status"] == "deleted":
                    update_fields["is_deleted"] = True
                    update_fields["deleted_at"] = datetime.utcnow()
            
            if "is_deleted" in comment_update and comment_update["is_deleted"] is not None:
                # 保持向后兼容
                update_fields["is_deleted"] = comment_update["is_deleted"]
                if comment_update["is_deleted"]:
                    update_fields["status"] = "deleted"
                    update_fields["deleted_at"] = datetime.utcnow()
                else:
                    update_fields["status"] = "published"
                    update_fields["deleted_at"] = None
            
            # 更新评论
            for field, value in update_fields.items():
                comments[comment_index][field] = value
            
            # 计算评论计数
            comment_count = len([c for c in comments if c.get("status") != "deleted" and not c.get("is_deleted", False)])
            
            # 更新数据库
            await self.db[collection_name].update_one(
                {"_id": ObjectId(entity_id)},
                {
                    "$set": {
                        "comments": comments,
                        "updated_at": datetime.utcnow(),
                        "comment_count": comment_count
                    }
                }
            )
            
            action = "撤销评论" if update_fields.get("status") == "deleted" or update_fields.get("is_deleted") else "更新评论"
            return {"message": f"{action}成功"}
            
        except HTTPException:
            raise
        except Exception as e:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail=f"更新评论失败: {str(e)}"
            )
    
    async def delete_comment(
        self,
        user: dict,
        entity_type: str,
        entity_id: str,
        comment_id: str,
        permanent: bool = False
    ) -> dict:
        """删除评论（默认软删除）"""
        try:
            # 验证实体ID格式
            if not ObjectId.is_valid(entity_id):
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="无效的实体ID格式"
                )
            
            # 构建集合名称
            collection_name = f"{entity_type}s"
            
            # 查询实体和评论
            entity = await self.db[collection_name].find_one({"_id": ObjectId(entity_id)})
            if not entity:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail=f"{entity_type.capitalize()}不存在"
                )
            
            # 查找评论
            comments = entity.get("comments", [])
            comment_index = -1
            for i, comment in enumerate(comments):
                if comment.get("id") == comment_id:
                    comment_index = i
                    break
            
            if comment_index == -1:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="评论不存在"
                )
            
            comment = comments[comment_index]
            
            # 检查评论是否已被删除
            comment_status = comment.get("status", "published")
            is_deleted = comment.get("is_deleted", False)
            if comment_status == "deleted" or is_deleted:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="评论已被删除"
                )
            
            # 权限检查
            comment_author_id = str(comment.get("author_id", comment.get("user_id", "")))
            user_roles = user.get("roles", [])
            
            # 永久删除需要管理员权限
            if permanent and "admin" not in user_roles:
                raise HTTPException(
                    status_code=status.HTTP_403_FORBIDDEN,
                    detail="只有管理员可以永久删除评论"
                )
            
            # 软删除只需要评论作者或管理员权限
            if not permanent:
                has_permission = (comment_author_id == user["user_id"] or "admin" in user_roles)
                if not has_permission:
                    raise HTTPException(
                        status_code=status.HTTP_403_FORBIDDEN,
                        detail="无权限删除此评论"
                    )
            
            if permanent:
                # 永久删除
                del comments[comment_index]
            else:
                # 软删除
                comments[comment_index]["status"] = "deleted"
                comments[comment_index]["is_deleted"] = True
                comments[comment_index]["deleted_at"] = datetime.utcnow()
                comments[comment_index]["updated_at"] = datetime.utcnow()
            
            # 计算评论计数
            comment_count = len([c for c in comments if c.get("status") != "deleted" and not c.get("is_deleted", False)])
            
            # 更新数据库
            await self.db[collection_name].update_one(
                {"_id": ObjectId(entity_id)},
                {
                    "$set": {
                        "comments": comments,
                        "updated_at": datetime.utcnow(),
                        "comment_count": comment_count
                    }
                }
            )
            
            return {"message": "删除评论成功"}
            
        except HTTPException:
            raise
        except Exception as e:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail=f"删除评论失败: {str(e)}"
            )
    
    async def get_comments(
        self,
        entity_type: str,
        entity_id: str,
        page: int = 1,
        page_size: int = 20,
        include_deleted: bool = False
    ) -> dict:
        """获取评论列表"""
        try:
            # 验证实体ID格式
            if not ObjectId.is_valid(entity_id):
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="无效的实体ID格式"
                )
            
            # 构建集合名称
            collection_name = f"{entity_type}s"
            
            # 查询实体
            entity = await self.db[collection_name].find_one({"_id": ObjectId(entity_id)})
            if not entity:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail=f"{entity_type.capitalize()}不存在"
                )
            
            # 获取评论列表
            comments = entity.get("comments", [])
            
            # 过滤已删除的评论
            if not include_deleted:
                comments = [
                    c for c in comments 
                    if c.get("status") != "deleted" and not c.get("is_deleted", False)
                ]
            
            # 按创建时间倒序排序
            comments.sort(key=lambda x: x.get("created_at", datetime.min), reverse=True)
            
            # 分页处理
            total = len(comments)
            start = (page - 1) * page_size
            end = start + page_size
            paginated_comments = comments[start:end]
            
            # 收集所有评论的作者ID
            author_ids = set()
            for comment in paginated_comments:
                author_id = comment.get("author_id") or comment.get("user_id")
                if author_id:
                    # 确保统一转换为字符串格式
                    author_id_str = str(author_id)
                    author_ids.add(author_id_str)
            
            # 从用户表批量查询用户信息
            users_map = {}
            if author_ids:
                # 尝试将字符串ID转换为ObjectId进行查询
                user_ids_list = []
                for uid in author_ids:
                    if ObjectId.is_valid(uid):
                        user_ids_list.append(ObjectId(uid))
                
                if user_ids_list:
                    async for user_doc in self.db.users.find({"_id": {"$in": user_ids_list}}):
                        # 使用字符串ID作为键
                        user_id_str = str(user_doc["_id"])
                        users_map[user_id_str] = user_doc
            
            # 格式化评论数据
            formatted_comments = []
            for comment in paginated_comments:
                # 兼容不同模块的字段命名，确保author_id为字符串
                raw_author_id = comment.get("author_id") or comment.get("user_id")
                author_id = str(raw_author_id) if raw_author_id else ""
                
                # 优先从用户表获取用户名，如果没有则使用评论中存储的用户名
                author_name = "未知用户"
                if author_id:
                    # 尝试从用户表获取用户名
                    # 首先尝试直接匹配字符串ID
                    user_doc = users_map.get(author_id)
                    if not user_doc and ObjectId.is_valid(author_id):
                        # 如果直接匹配失败，尝试将author_id转换为ObjectId再转回字符串进行匹配
                        try:
                            normalized_id = str(ObjectId(author_id))
                            user_doc = users_map.get(normalized_id)
                        except:
                            pass
                    
                    if user_doc:
                        author_name = user_doc.get("username") or user_doc.get("name") or "未知用户"
                    else:
                        # 如果用户表中没有，则使用评论中存储的用户名
                        author_name = comment.get("author_name") or comment.get("user_name") or "未知用户"
                else:
                    # 如果没有author_id，尝试从评论中获取用户名
                    author_name = comment.get("author_name") or comment.get("user_name") or "未知用户"
                
                # 处理评论ID（兼容旧数据可能没有id字段的情况）
                comment_id = comment.get("id")
                if not comment_id:
                    # 如果评论没有id字段，生成一个（用于显示，但不建议）
                    comment_id = str(ObjectId())
                
                formatted_comment = {
                    "id": str(comment_id),
                    "content": comment.get("content", ""),
                    "author_id": author_id,
                    "author_name": author_name,
                    "user_id": author_id,  # 保持向后兼容
                    "user_name": author_name,  # 保持向后兼容
                    "parent_comment_id": comment.get("parent_comment_id") or comment.get("parent_id"),
                    "status": comment.get("status", "published"),
                    "is_deleted": comment.get("is_deleted", False),
                    "created_at": comment.get("created_at"),
                    "updated_at": comment.get("updated_at"),
                    "deleted_at": comment.get("deleted_at")
                }
                formatted_comments.append(formatted_comment)
            
            return {
                "items": formatted_comments,
                "total": total,
                "page": page,
                "page_size": page_size,
                "message": "获取评论列表成功"
            }
            
        except HTTPException:
            raise
        except Exception as e:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail=f"获取评论列表失败: {str(e)}"
            )
